package com.etone.smartAudit.service;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.etone.smartAudit.domain.Admin;
import com.etone.smartAudit.domain.AdminMenu;
import com.etone.smartAudit.domain.AdminRole;
import com.etone.smartAudit.dto.adminMenu.AdminMenuDTO;
import com.etone.smartAudit.enums.StateType;
import com.etone.smartAudit.error.CustomParameterizedException;
import com.etone.smartAudit.mapper.AdminMenuMapper;
import com.etone.smartAudit.mapper.PermissionMapper;
import com.etone.smartAudit.mapstruct.AdminMenuMapstruct;
import com.etone.smartAudit.utils.BooleanUtil;
import com.etone.smartAudit.vo.menu.MenuVO;
import com.etone.smartAudit.vo.permission.PermissionSimpleVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author: 蒋学伟
 * @create: 2020-06-10 09:06:53
 * @Description AdminMenuService
 */
@Service
public class AdminMenuService extends ServiceImpl<AdminMenuMapper, AdminMenu> {

    @Autowired
    private AdminMenuMapstruct adminMenuMapstruct;

    @Autowired
    private AdminPermissionService adminPermissionService;

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private AdminRoleService roleService;

    /**
     * 管理员拥有菜单
     *
     * @param admin
     * @return
     */
    public List<MenuVO> findAdminMenus(Admin admin) {
        if (admin.isAdmin()) {
            return findAllMenus();
        }
        return toChildren(baseMapper.findByAdminId(admin.getId()), null, null);
    }

    /**
     * 管理员拥有菜单
     *
     * @param roleId
     * @return
     */
    public List<MenuVO> findRoleMenus(Integer roleId) {
        return toChildren(baseMapper.findByRoleId(roleId), null, null);
    }

    /**
     * 获取所有菜单
     *
     * @return
     */
    public List<MenuVO> findAllMenus() {
        return toChildren(baseMapper.findAll(), null, null);
    }


    /**
     * 递归 pid转children
     *
     * @param menus
     * @param pid
     * @param level 从1开始
     * @return
     */
    private List<MenuVO> toChildren(List<MenuVO> menus, Integer pid, Integer level) {
        int flagLevel = level == null ? 1 : (level + 1);
        Integer pIdFlag = pid == null ? 0 : pid;
        List<MenuVO> children = new ArrayList<>();
        menus.forEach(menuVO -> {
            if (pIdFlag.intValue() == menuVO.getPId().intValue()) {
                menuVO.setLevel(flagLevel);
                children.add(menuVO);
                menuVO.setChildren(toChildren(menus, menuVO.getId(), flagLevel));
            }
        });

        return children;
    }

    public AdminMenu get(Integer id) {
        AdminMenu adminMenu = getById(id);
        if (adminMenu == null) {
            throw new CustomParameterizedException("菜单不存在");
        }
        return adminMenu;
    }

    /**
     * 查询是否存在
     *
     * @param id
     * @return
     */
    public Boolean exists(Integer id) {
        return baseMapper.exists(id);
    }

    /**
     * 查询是否存在，并抛异常
     *
     * @param id
     * @return
     */
    public void existsThrow(Integer id) {
        Boolean exists = exists(id);
        if (BooleanUtil.isFalse(exists)) {
            throw new CustomParameterizedException("菜单不存在");
        }
    }

    /**
     * 增加|编辑菜单
     *
     * @param id
     * @param adminMenuDTO
     */
    @Transactional(rollbackFor = Exception.class)
    public void save(Integer id, AdminMenuDTO adminMenuDTO) {
        AdminMenu adminMenu;
        if (id == null) {
            adminMenu = AdminMenu.builder().state(StateType.ENABLE).build();
        } else {
            adminMenu = get(id);
        }
        adminMenuMapstruct.copt2AdminMenu(adminMenu, adminMenuDTO);

        saveOrUpdate(adminMenu);

        //更新菜单权限
        adminPermissionService.updateMenuPermission(adminMenu.getId(), adminMenuDTO.getPermissionIds());
    }

    /**
     * 菜单详情
     *
     * @param id
     * @return
     */
    public MenuVO detail(Integer id) {
        AdminMenu adminMenu = get(id);
        MenuVO menuVO = adminMenuMapstruct.getMenuVO(adminMenu);
        List<PermissionSimpleVO> permissionSimpleVOS = adminPermissionService.getBaseMapper().findByMenuId(id);
        menuVO.setPermissionSimples(permissionSimpleVOS);
        return menuVO;
    }

    /**
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    public void delete(Integer id) {
        //本菜单是否存在
        existsThrow(id);

        //判断是否有子菜单
        Boolean hasChildrenMenu = hasChildrenMenu(id);
        if (hasChildrenMenu) {
            throw new CustomParameterizedException("无法删除该菜单，请先删除子菜单");
        }
        removeById(id);
    }

    /**
     * 查找是否有子菜单
     *
     * @param id
     * @return
     */
    public Boolean hasChildrenMenu(Integer id) {
        return baseMapper.hasChildrenMenu(id);
    }


    public List<MenuVO> findMenusTreeV2(Integer roleId, Admin admin) {
        List<MenuVO> vo = findMenusTree(roleId, admin);


        return null;
    }

    /***
     * 获取菜单树
     * @param roleId
     * @return
     */
    public List<MenuVO> findMenusTree(Integer roleId, Admin admin) {
//        return toChildren(baseMapper.findAll(), null, null);
        if (roleId == null) {
            throw new CustomParameterizedException("角色id不能为空");
        }
        //获取所有菜单
        List<MenuVO> all = baseMapper.getAll();
        //获取当前角色是否是超级管理员
        AdminRole adminRole = roleService.get(roleId);
        if ("R_ADMIN".equals(adminRole.getCode())) {

            return toTree(all, null, null, new ArrayList<>(), new HashMap<>(), true);
        }
        //获取角色拥有的菜单
        List<MenuVO> roleMenu = baseMapper.findByRoleId(roleId);

        //获取菜单对应拥有的权限
        List<PermissionSimpleVO> rolePermissions = permissionMapper.findSimpleByRoleId(roleId);
        List<Integer> roleMenuIds = roleMenu.stream().map(MenuVO::getId).collect(Collectors.toList());

        Map<Integer, List<Integer>> rolePermissionMap = new HashMap<>();
        Integer defalut = -10001;
        rolePermissions.stream().forEach(p -> {
            String parentIds = p.getParentIds();
            Integer id = p.getId();
            if (StrUtil.isEmpty(parentIds)) {
                //默认初始化一个菜单
                List<Integer> list = rolePermissionMap.get(defalut);
                if (list == null) {
                    list = new ArrayList<>();
                    rolePermissionMap.put(defalut, list);
                }
                list.add(id);
            } else {
                String[] keys = parentIds.split(",");
                for (String k : keys) {
                    try {
                        Integer menuId = Integer.valueOf(k);
                        List<Integer> list = rolePermissionMap.get(menuId);
                        if (list == null) {
                            list = new ArrayList<>();
                            rolePermissionMap.put(menuId, list);
                        }
                        list.add(id);
                    } catch (Exception e) {
                        log.error("菜单id不正确", e);
                    }

                }
            }
        });

        return toTree(all, null, null, roleMenuIds, rolePermissionMap, false);
//        return null;
    }

    /**
     * 递归 pid转children
     *
     * @param menus
     * @param pid
     * @param level             从1开始
     * @param roleMenuIds
     * @param rolePermissionMap
     * @return
     */
    private List<MenuVO> toTree(List<MenuVO> menus, Integer pid, Integer level, List<Integer> roleMenuIds, Map<Integer, List<Integer>> rolePermissionMap, boolean isAdmin) {
        int flagLevel = level == null ? 1 : (level + 1);
        Integer pIdFlag = pid == null ? 0 : pid;
        List<MenuVO> children = new ArrayList<>();
        menus.forEach(menuVO -> {
            if (pIdFlag.intValue() == menuVO.getPId().intValue()) {
                menuVO.setLevel(flagLevel);
                Integer id = menuVO.getId();
                if (isAdmin) {
                    menuVO.setSelected(true);
                } else if (roleMenuIds != null && roleMenuIds.contains(id)) {
                    menuVO.setSelected(true);
                }
                List<PermissionSimpleVO> permiss = menuVO.getPermissionSimples();
                List<Integer> perIds = rolePermissionMap.get(id);
                permiss.stream().forEach(p -> {
                    Integer persionId = p.getId();
                    if (isAdmin) {
                        p.setSelected(true);
                    } else if (perIds != null && perIds.contains(persionId)) {
                        p.setSelected(true);
                    }
                });
                children.add(menuVO);
                menuVO.setChildren(toTree(menus, menuVO.getId(), flagLevel, roleMenuIds, rolePermissionMap, isAdmin));
            }
        });

        return children;
    }

    /**
     * 获取角色是否拥有指定的菜单
     *
     * @param menuId
     * @param roleId
     * @return
     */
    public Integer getMenuByRoleIdAndMenuId(Integer menuId, Integer roleId) {
        Integer count = permissionMapper.getMenuByRoleIdAndMenuId(menuId, roleId);
        return count == null ? 0 : count;
    }
}
